import { createAlova } from 'alova';
import adapterFetch from 'alova/fetch';
import ReactHook from 'alova/react';

// import { loginSsoLogoutInfo } from '@/api/login';
import { mapStg } from '@/utils/storage';

import type { RequestBody } from 'alova';

/**
 * 统一的API响应接口
 */
export interface ApiResponse<T = any> {
  /**
   * 响应数据
   */
  data: T;

  /**
   * 错误码
   */
  errorCode: number;

  /**
   * 错误信息
   */
  errorMsg: string;

  /**
   * 请求是否成功
   */
  success: boolean;

  /**
   * 时间戳
   */
  timestamp: number;
  [key: string]: any;
}

/** 白名单 - 不需要验证 token 的接口 */
const whiteList = ['/login', '/register', '/forgot-password', '/refresh-token'];

const showLog = false;

/** HTTP 状态码常量 */
const HTTP_STATUS = {
  OK: 200,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  INTERNAL_SERVER_ERROR: 500,
} as const;

/** 业务状态码常量 */
const BUSINESS_CODE = {
  SUCCESS: 200,
  UNAUTHORIZED: 401,
  TOKEN_EXPIRED: 402,
  FORBIDDEN: 403,
} as const;

/** Loading 管理器 */
class LoadingManager {
  private static instance: LoadingManager;
  private loadingCount = 0;
  private loadingTimer: NodeJS.Timeout | null = null;

  static getInstance(): LoadingManager {
    if (!LoadingManager.instance) {
      LoadingManager.instance = new LoadingManager();
    }
    return LoadingManager.instance;
  }

  /** 显示 loading */
  showLoading(delay = 200): void {
    this.loadingCount++;

    // 防抖处理，避免快速请求时的闪烁
    if (this.loadingTimer) {
      clearTimeout(this.loadingTimer);
    }

    this.loadingTimer = setTimeout(() => {
      if (this.loadingCount > 0 && window.$loading?.show) {
        window.$loading.show();
      }
    }, delay);
  }

  /** 隐藏 loading */
  hideLoading(): void {
    this.loadingCount = Math.max(0, this.loadingCount - 1);

    if (this.loadingCount === 0) {
      if (this.loadingTimer) {
        clearTimeout(this.loadingTimer);
        this.loadingTimer = null;
      }

      if (window.$loading?.hide) {
        window.$loading.hide();
      }
    }
  }

  /** 强制隐藏 loading */
  forceHide(): void {
    this.loadingCount = 0;
    if (this.loadingTimer) {
      clearTimeout(this.loadingTimer);
      this.loadingTimer = null;
    }
    if (window.$loading?.hide) {
      window.$loading.hide();
    }
  }

  /** 获取当前loading状态 */
  get isLoading(): boolean {
    return this.loadingCount > 0;
  }
}

const loadingManager = LoadingManager.getInstance();

/** 检查是否在白名单中 */
const isInWhiteList = (url: string): boolean => {
  return whiteList.some(path => url.includes(path));
};

/** 处理 token 过期 */
const handleTokenExpired = (): void => {
  // 避免重复弹窗
  if (window.__tokenExpiredModalShown) {
    return;
  }
  window.__tokenExpiredModalShown = true;

  // 先强制隐藏所有loading
  loadingManager.forceHide();

  if (window.$modal?.info) {
    window.$modal.info({
      title: '登录状态已过期',
      content: '您的登录状态已过期，请重新登录以继续使用',
      okText: '重新登录',
      cancelText: '取消',
      maskClosable: false,
      onOk: () => {
        // loginSsoLogoutInfo();
        mapStg.remove('token');
        mapStg.remove('userInfo');
        mapStg.remove('isLogin');
        window.__tokenExpiredModalShown = false;
        // 使用 replace 避免回退到需要登录的页面
        window.location.replace('#/login');
      },
      onCancel: () => {
        window.__tokenExpiredModalShown = false;
      },
    });
  } else {
    // 如果没有modal组件，直接跳转
    console.warn('$modal not available, redirecting to login');
    mapStg.remove('token');
    mapStg.remove('userInfo');
    window.__tokenExpiredModalShown = false;
    window.location.replace(`#${import.meta.env.VITE_HOME_URL ?? '/login'}`);
  }
};

/** 显示错误消息 */
const showErrorMessage = (msg: string, isShowMsg = true): void => {
  console.log('[ msg ] >', msg);
  if (window.$message?.error && isShowMsg) {
    window.$message.destroy();
    window.$message.error(msg ?? '服务异常，请稍后重试');
  } else {
    console.error('API Error:', msg);
    // 可以在这里添加其他错误提示方式，比如toast
  }
};

/** 需要跳过loading的路径 */
const skipLoadingPaths = ['/heartbeat', '/ping', '/health'];

const fetchClient = createAlova({
  baseURL: import.meta.env.VITE_BASE_API,
  timeout: 10000,
  cacheFor: null,
  statesHook: ReactHook,
  requestAdapter: adapterFetch(),

  beforeRequest: method => {
    // 自动显示 loading（跳过某些不需要 loading 的请求）
    const shouldShowLoading = !skipLoadingPaths.some(path => method.url.includes(path));

    if (shouldShowLoading) {
      // 检查是否禁用自动 loading
      const disableLoading =
        method.meta?.disableLoading ?? method.config.headers?.['X-Disable-Loading'] === 'true';

      if (!disableLoading) {
        loadingManager.showLoading();
      }
    }
    if (method.meta?.baseURL) {
      method.baseURL = method.meta.baseURL;
    }
    // console.log('method.config.headers', method.url);
    // 设置默认请求头
    method.config.headers = {
      // 'Content-Type': 'application/json',
      ...method.config.headers,
    };
    const token = mapStg.get('token', '');
    if (token) {
      method.config.headers['Authorization'] = `Bearer ${token}`;
    }
    loadingManager.hideLoading();
    // 检查是否需要添加 token
    if (!method.meta?.auth && !isInWhiteList(method.url)) {
      if (!token) {
        // 隐藏 loading
        // 对于需要 token 但没有 token 的请求，直接处理登录过期
        handleTokenExpired();
        throw new Error('Token not found'); // 使用 throw 而不是 Promise.reject
      }
    }

    // 开发环境下打印请求信息
    if (import.meta.env.DEV && showLog) {
      console.log(`🚀 API Request: ${method.type} ${method.url}`, {
        headers: method.config.headers,
        data: method.data,
      });
    }
  },

  responded: {
    onSuccess: async (response, method) => {
      // 隐藏 loading
      loadingManager.hideLoading();
      // 检查是否为文件下载请求（responseType 为 blob 或 arraybuffer）
      const responseType = method.config.headers?.['responseType'] || method.meta?.responseType;
      const isFileDownload = responseType === 'blob' || responseType === 'arraybuffer';

      if (isFileDownload) {
        // 对于文件下载，直接返回原始响应
        if (import.meta.env.DEV && showLog) {
          console.log(`📁 File Download Response: ${method.type} ${method.url}`, {
            status: response.status,
            contentType: response.headers.get('content-type'),
            contentLength: response.headers.get('content-length'),
          });
        }
        return response;
      }

      let isShowMsg = true;
      try {
        const dataJSON = await response.json();
        // 开发环境下打印响应信息
        if (import.meta.env.DEV && showLog) {
          console.log(`✅ API Response: ${method.type} ${method.url}`, dataJSON);
        }

        // 检查响应数据结构
        if (!dataJSON) {
          console.warn('Response data is empty:', response);
          return response;
        }
        const { errorCode, error } = dataJSON;
        const errorMsg = dataJSON.errorMsg ?? error;
        if (
          method.url.includes('/sso/getRedirectUrl') ||
          method.url.includes('/user/checkEnterpriseAdmin')
        ) {
          isShowMsg = false;
        }
        // 如果没有code字段，可能是直接返回数据的接口
        if (errorCode === undefined) {
          if (errorMsg) {
            showErrorMessage(errorMsg ?? '请求失败', isShowMsg);
          }
          return dataJSON;
        }

        // 处理不同的业务状态码
        switch (errorCode) {
          case BUSINESS_CODE.SUCCESS:
            return dataJSON;

          case BUSINESS_CODE.UNAUTHORIZED:
          case BUSINESS_CODE.TOKEN_EXPIRED:
            handleTokenExpired();
            showErrorMessage(errorMsg ?? '权限不足', isShowMsg);
            throw new Error(errorMsg ?? '登录已过期');

          case BUSINESS_CODE.FORBIDDEN:
            showErrorMessage(errorMsg ?? '权限不足', isShowMsg);
            throw new Error(errorMsg ?? '权限不足');

          default:
            showErrorMessage(errorMsg ?? '请求失败', isShowMsg);
            throw new Error(errorMsg ?? '请求失败');
        }
      } catch (error: unknown) {
        // 处理错误
        let errorMessage = '服务异常';

        if (error instanceof Error) {
          errorMessage = error.message;
        } else if (typeof error === 'string') {
          errorMessage = error;
        }
        showErrorMessage(errorMessage);
      }
    },

    onError: (error, method) => {
      // 隐藏 loading
      loadingManager.hideLoading();

      // 开发环境下打印错误信息
      if (import.meta.env.DEV && showLog) {
        console.error(`❌ API Error: ${method.type} ${method.url}`, error);
      }

      const { response } = error;
      let errorMessage = '网络请求失败';

      if (response) {
        const { status, statusText } = response;

        // 处理不同的 HTTP 状态码
        switch (status) {
          case HTTP_STATUS.UNAUTHORIZED:
            handleTokenExpired();
            errorMessage = '登录已过期';
            break;

          case HTTP_STATUS.FORBIDDEN:
            errorMessage = '权限不足';
            break;

          case HTTP_STATUS.NOT_FOUND:
            errorMessage = '接口不存在';
            break;

          case HTTP_STATUS.INTERNAL_SERVER_ERROR:
            errorMessage = '服务器内部错误';
            break;

          default:
            try {
              // 尝试解析错误响应
              const errorData = response.data;
              errorMessage = errorData?.message || statusText || `请求失败 (${status})`;
            } catch {
              errorMessage = statusText || `请求失败 (${status})`;
            }
        }
      } else if (error.name === 'AbortError') {
        errorMessage = '请求已取消';
        // 请求取消时不显示错误消息
        return Promise.reject(error);
      } else if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
        errorMessage = '请求超时，请稍后重试';
      } else if (!navigator.onLine) {
        errorMessage = '网络连接失败，请检查网络设置';
      }

      showErrorMessage(errorMessage);
      return Promise.reject(error);
    },
  },
});

export function apiGet<T = unknown>(url: string, config = {}) {
  return fetchClient.Get<ApiResponse<T>>(url, config);
}

export function apiPost<T = unknown>(url: string, data: RequestBody, config = {}) {
  return fetchClient.Post<ApiResponse<T>>(url, data, config);
}

export function apiPut<T = unknown>(url: string, data: RequestBody, config = {}) {
  return fetchClient.Put<ApiResponse<T>>(url, data, config);
}

export function apiDelete<T = unknown>(url: string, config = {}) {
  return fetchClient.Delete<ApiResponse<T>>(url, config);
}

/**
 * 文件下载请求 - 返回 Blob
 * @param url 请求地址
 * @param config 请求配置
 * @returns Promise<Response> 原始响应对象
 */
export function apiDownloadBlob(url: string, config: Record<string, unknown> = {}) {
  return fetchClient.Get(url, {
    ...config,
    meta: {
      ...(config.meta as Record<string, unknown>),
    },
    headers: {
      responseType: 'blob',
    },
  });
}

/**
 * 文件下载请求 - 返回 ArrayBuffer
 * @param url 请求地址
 * @param config 请求配置
 * @returns Promise<Response> 原始响应对象
 */
export function apiDownloadArrayBuffer(url: string, config: Record<string, unknown> = {}) {
  return fetchClient.Get(url, {
    ...config,
    meta: {
      ...(config.meta as Record<string, unknown>),
    },
    headers: {
      responseType: 'arraybuffer',
    },
  });
}

/**
 * POST 方式文件下载请求 - 返回 Blob
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<Response> 原始响应对象
 */
export function apiDownloadBlobPost(
  url: string,
  data: RequestBody,
  config: Record<string, unknown> = {}
) {
  return fetchClient.Post(url, data, {
    ...config,
    meta: {
      ...(config.meta as Record<string, unknown>),
    },
    headers: {
      responseType: 'blob',
    },
  });
}
const apiClient = {
  Get: apiGet,
  Post: apiPost,
  Put: apiPut,
  Delete: apiDelete,
  DownloadBlob: apiDownloadBlob,
  DownloadArrayBuffer: apiDownloadArrayBuffer,
  DownloadBlobPost: apiDownloadBlobPost,
};

// 导出 loading 管理器，供外部使用
export { loadingManager };
export default apiClient;
